home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / MISC / MAG07.ZIP / MAG07.TXT < prev    next >
Encoding:
Text File  |  1996-04-08  |  62.7 KB  |  1,545 lines

  1. Spellcaster presents:
  2.  
  3.  
  4. TTTTTTTTTT HH      HH EEEEEEEEEE    MM      MM    AAAA     GGGGGGGGG
  5.     TT     HH      HH EE            MMM    MMM   AA  AA   GG
  6.     TT     HH      HH EE            MM M  M MM  AA    AA  GG  
  7.     TT     HHHHHHHHHH EEEEEE        MM  MM  MM  AAAAAAAA  GG   
  8.     TT     HH      HH EE            MM      MM  AA    AA  GG    GGGG
  9.     TT     HH      HH EE            MM      MM  AA    AA  GG      GG
  10.     TT     HH      HH EEEEEEEEEE    MM      MM  AA    AA   GGGGGGGG
  11.  
  12.                                                         Issue 7
  13.                                                         6-4-96
  14.  
  15.  
  16. -x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-
  17.  
  18.  
  19.   Index:
  20.  
  21.         1. Introduction
  22.           1.1. About the magazine
  23.           1.2. About the author
  24.           1.3. Distribution
  25.           1.4. Contribuitions
  26.           1.5. Hellos and greets
  27.         2. Mail Room
  28.         3. 'Unit Gfx, Please Respond' - A true story
  29.           3.1. What the hell is a Unit ?????
  30.           3.2. Defining a Unit
  31.               3.2.1. Interface
  32.               3.2.2. Implementation
  33.               3.2.3. Startup-Code
  34.               3.2.4. The final Unit
  35.               3.2.5. Valid and invalid instruction
  36.           3.3. Other Unit-related stuff
  37.           3.4. The CRT Unit
  38.         4. Boolean Algebra - Another look at conditions
  39.           4.1. NOT
  40.           4.2. AND
  41.           4.3. OR
  42.           4.4. XOR
  43.           4.5. Rules of Boolean Algebra
  44.           4.6. Using Boolean algebra
  45.         5. Our friend, the pointer - Part II
  46.         6. The Lens Effect
  47.           6.1. Transformations
  48.           6.2. How to make the lens transformation
  49.         7. Graphics Part VI - Scrolling Part I
  50.           7.1. What is scrolling ?
  51.           7.2. Wipe Scrolls
  52.           7.3. Other Scrolls
  53.         8. Hints and tips
  54.         9. Points of view
  55.        10. The adventures of Spellcaster, part 7
  56.  
  57.  
  58. -x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-
  59.  
  60.  
  61.   1. Introduction
  62.  
  63.     1.1. About the magazine
  64.  
  65.     Welcome to number 7 of 'The Mag', brought to you, as usual, by Spellcaster,
  66.   alias Diogo de Andrade. This issue is quite large (for me, of course, that
  67.   have to write it...).
  68.     I know I told you last issue that I could put in this issue the first of
  69.   the Spellcaster Utilities... Well, I didn't had time to code it, with other
  70.   projects and stuff, so I think I'll postpone the utilities for the Easter
  71.   vacation... If you have any suggestions for them, write to me...
  72.     Also, a little add... I'm trying to change the logo on top, the one that
  73.   says 'THE MAG', but my ANSI art sucks !! In fact, all my art sucks !!! I was
  74.   born to code... :) So, if anyone out there wants to do a better logo for me,
  75.   go ahead !!! NOTE- No strange codes, just plain ASCII chars... Not even
  76.   ASCII-E characters, because I use (and sometimes write) this in a UNIX
  77.   machine, and I don't know how to configure the simbols on the screen... :(
  78.  
  79.     This magazine is dedicated to all the programmers and would-be programmers
  80.   out there, especially to those that can't access the Net easily to get
  81.   valuable information, to those who wish to learn how to program anything,
  82.   from demos to games, passing through utilities and all sort of thing your
  83.   mind can think of, and to those that can't find the right information.
  84.  
  85.     When you read this magazine, I'll assume some things. First, I assume you
  86.   have Borland's Turbo Pascal, version 6 and upwards (and TASM for the assembly
  87.   tutorials). I'll also think you have a 80386 (or 386 for short; a 486 would
  88.   be even better), a load of patience and a sense of humor. This last is almost
  89.   essencial, because I don't receive any money for doing this, so I must have
  90.   fun doing it. I will also take for certain you have the 9th grade (or
  91.   equivelent). Finally, I will assume that you have the last issues of
  92.   'The Mag', and that you have grasped the concepts I tried to transmit. If
  93.   you don't have the issues, you can get them by mail, writing to one of the
  94.   adresses shown below (Snail mail and Email).
  95.  
  96.     As I stated above, this magazine will be made especially for those who don't
  97.   know where to get information, or want it all in the same place, and to those
  98.   who want to learn how to program, so I'll try to build knowledge, building up
  99.   your skills issue by issue. If you sometimes fail to grasp some concept, don't
  100.   despair; try to work it out.
  101.     That's what I did... Almost everything I know was learnt from painfull
  102.   experience. If you re-re-re-read the article, and still can't understand it,
  103.   just drop a line, by mail, or just plain forget it. Most of the things I 
  104.   try to teach here aren't linked to each other (unless I say so), so if you
  105.   don't understand something, skip it and go back to it some weeks later. It
  106.   should be clearer for you then. Likewise, if you see any terms or words you 
  107.   don't understand, follow the same measures as before.
  108.  
  109.     Ok, as I'm earing the Net gurus and other god-like creatures talking
  110.   already, I'm just going to explain why I use Pascal.
  111.   For starters, Pascal is a very good language, ideal for the beginner, like 
  112.   BASIC (yech!), but it's powerfull enough to make top-notch programms.
  113.   Also, I'll will be using assembly language in later issues, and Pascal makes
  114.   it so EASY to use. 
  115.   Finally, if you don't like my choice of language, you can stop whining. The
  116.   teory behind each article is very simple, and common with any of the main
  117.   languages (C, C++, Assembly - Yes, that's true... BASIC isn't a decent
  118.   language).
  119.  
  120.     Just one last thing... The final part of the magazine is a little story
  121.   made up by my distorted mind. It's just a little humor I like to write, and
  122.   it hasn't got nothing to do with programming (well, it has a little), but, 
  123.   as I said before, I just like to write it.
  124.  
  125.     1.2. About the author
  126.  
  127.     Ok, so I'm a little egocentric, but tell me... If you had the trouble of 
  128.   writing hundreds of lines, wouldn't you like someone to know you, even by 
  129.   name ?
  130.  
  131.     My name is Diogo de Andrade, alias Spellcaster, and I'm the creator, 
  132.   editor and writer of this magazine. 
  133.     I live in a small town called Setubal, just near Lisbon, the capital of
  134.   Portugal... If you don't know where it is, get an encyclopedia, and look for
  135.   Europe. Then, look for Spain. Next to it, there's Portugal, and Setubal is in
  136.   the middle.
  137.  
  138.     I'm 18 years old, and I just made it in to the university (if you do want
  139.   to know, I'm in the Technical Institute of Lisbon, Portugal), so I'm not 
  140.   a God-Like creature, with dozens of years of practice (I only program by 
  141.   eight years now, and I started in a Spectrum, progressing later to an Amiga.
  142.   I only program in the PC for a year or so), with a mega-computer (I own a 
  143.   386SX, 16 Mhz), that wear glasses with lens that look like the bottom of a 
  144.   bottle (I use glasses, but only sometimes), that has his head bigger than a 
  145.   pumpkin (I have a normal sized head) and with an IQ of over 220 (mine is 
  146.   actually something like 180-190). I can program in C, C++, Pascal, Assembly
  147.   and even BASIC (yech!).
  148.  
  149.     So, if I am a normal person, why do I spend time writing this ?
  150.   Well, because I have the insane urge to write thousands of words every now
  151.   and then, and while I'm at it, I may do something productive, like teaching
  152.   someone. I may be young, but I know a lot about computers (how humble I am;
  153.   I know, modesty isn't one of my qualities).
  154.  
  155.     Just one more thing, if you ever program anything, please send to me... I
  156.   would love to see some work you got, maybe I could learn something with it.
  157.   Also, give me a greet in your program/game/demo... I love seeing my name.
  158.  
  159.     1.3. Distribution
  160.  
  161.     I don't really know when can I do another issue, so, there isn't a fixed
  162.   space of time between two issues. General rule, I will try to do one every two
  163.   weeks, maybe more, probably less (Eheheheh). This is getting to an issue
  164.   every month, so, I'll think I'll change the above text... :)
  165.     'The Mag' is available by the following means:
  166.  
  167.     - Snail Mail : My address is below, in the Contributions seccion... Just
  168.                    send me a disk and tell me what issues you want, and I
  169.                    will send you them...
  170.  
  171.     - E-Mail : If you E-mail me and ask me for some issues, I will Email you
  172.                back with the relevant issues attached.
  173.  
  174.     - BBS's : I don't know for sure what BBS's have or will have my magazine,
  175.               but I will try to post it in the Skyship BBS.
  176.               If you have a BBS and you want to receive 'The Mag', contact me.
  177.  
  178.                  Skyship BBS numbers: (351)+01-3158088
  179.                                       (351)+01-3151435
  180.  
  181.     - Internet : You can access the Spellcaster page and take the issues out
  182.                  of there in:
  183.  
  184.                  http://alfa.ist.utl.pt/~l42686
  185.  
  186.     1.4. Contributions
  187.  
  188.     I as I stated before, I'm not a God... I do make mistakes, and I don't 
  189.   have (always) the best way of doing things. So, if you think you've spotted
  190.   an error, or you have thought of a better way of doing things, let me know.
  191.   I'll be happy to receive anything, even if it is just mail saying 'Keep it 
  192.   up'. As all human beings, I need incentive.
  193.  
  194.     Also, if you do like to write, please do... Send in articles, they will be
  195.   welcome, and you will have the chance to see your names up in lights.
  196.     They can be about anything, for a review of a book or program that can
  197.   help a programmer, to a point of view or a moan. I'm specially interested in
  198.   articles explaining XMS, EMS, DMA and Soundblaster/GUS.
  199.  
  200.     If anyone out there has a question or wants to see an article about 
  201.   something in particular, feel free to write... All letters will be answered,
  202.   provided you give me your address.
  203.  
  204.     I'm also trying to start a new demo/game/utility group, and I need all sort 
  205.   of people, from coders (sometimes, one isn't enough), musicians (I can 
  206.   compose, but I'm a bit limited), graphics artists (I can't draw nothing) and
  207.   spreaders... I mean, by a spreader, someone who spreads things, like this mag.
  208.   If you have a BBS and you want it to include this magazine, feel free to
  209.   write me... I don't have a modem, so I can only send you 'The Mag' by Email.
  210.  
  211.     You can also contact me personally, if you study on the IST (if you don't
  212.   know what the IST is, you don't study there). I'm the freshman with the
  213.   black hair and dark-brown eyes... Yes, the very_beutifull_but_not_so_tall_guy
  214.   who spends ALL his time on campus...
  215.  
  216.     My adress is:
  217.                  Praceta Carlos Manito Torres, nº4/6ºC
  218.                  2900 Setúbal
  219.                  Portugal
  220.  
  221.     Email: dgan@rnl.ist.utl
  222.            l42686@alfa.ist.utl.pt
  223.  
  224.     And if you want to contact me on the lighter side, get into one of the
  225.   following talkers... To do that telnet to:
  226.  
  227.           Lost Eden -> Alfa.Ist.Utl.Pt  : Port 1414
  228.  
  229.               Talho -> Ubistc.Ubi.Pt    : Port 7000
  230.  
  231.               CItal -> Zeus.Ci.Ua.Pt    : Port 6969
  232.  
  233.     I'm almost always there in the afternoon... As you may have guessed already,
  234.   my handle is Spellcaster (I wonder why...)...
  235.  
  236.     1.5. Hellos and greets
  237.  
  238.     I'll say hellos and thanks to all my friend, especially for those who put 
  239.   up with my constant whining.
  240.     Special greets go to Denthor from Asphyxia (for the excelent VGA trainers),
  241.   Draeden from VLA (for assembly tutorials), Joaquim Elder Guerreiro, alias
  242.   Dr.Shadow (Delta Team is still up), Joao Neves for sugestions, testing and
  243.   BBS services, and all the demo groups out there.
  244.     I will also send greets to everybody that responded to my mag... Thank
  245.   you very much !
  246.     Special hails go to: Ricardo 'Scorpio' Oliveira... Check out his page,
  247.   it's great !! :)
  248.  
  249.  
  250. -x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-
  251.  
  252.  
  253.   2. Mail Room
  254.  
  255.     I've received a mail from a person that shall remain nameless (right,
  256.   Greg ? :) ), asking were can we get information about coding on the Net.
  257.   I'm no expert on InterNet, but I know a couple of sites were you can get
  258.   stuff:
  259.  
  260.         - The Hornet Demo Archive: ftp.cdrom.com
  261.             This site has _LOTS_ of stuff, including complete source code
  262.             of some demos, and tutorials made by several demopeople.
  263.             Besides source code and tutorials, you can get there all
  264.             demos made by man... Well, almost all... :)
  265.  
  266.         - The Asphyxia Page: (don't remember the URL)
  267.             This is the home site of the Asphyxia VGA Tutorials, made by
  268.             Denthor... These are very recomendable tutorials, the best there
  269.             are !! I love them, and it was they who got me into demo/game
  270.             coding... They are similar to my Graphics tutorials, only better
  271.             done... :)
  272.  
  273.         - Scorpio's Homepage: (I also don't remember this URL)
  274.             This is the homepage of a friend of mine here in Portugal... He's
  275.             a lot into DemoCoding, so he has LOTS and I mean LOTS of links to
  276.             code related pages... Go get them !!
  277.  
  278.         - My home page: http://alfa.ist.utl.pt/~l42686
  279.             My home page doesn't really have much about coding, except for
  280.             'The Mag'... But you have there more links to other pages full of
  281.             coding info... You can find the URL of the Asphyxia Page and of the
  282.             Scorpio HomePage there...
  283.  
  284.   -----------------------------------------------------------------------------
  285.  
  286.     Because of various letters, I'm posting here an errata to 'The Mag'... It
  287.   seems that, when I gave the SetColor procedure (back in issue 3) I made I
  288.   mistake when writing it... The header of that procedure is like this:
  289.  
  290.                Procedure SetColor(Col,R,B,G:Byte);
  291.  
  292.     and it should be like this:
  293.  
  294.                Procedure SetColor(Col,R,G,B:Byte);
  295.  
  296.     You must swap the B and G variables... If you do this, the procedure should
  297.   work fine... Thanks to the people that spotted this error...
  298.  
  299.  
  300. -x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-
  301.  
  302.   3. 'Unit GFX, Please Respond' - A true story
  303.  
  304.     For starters, let me just say that the title of the article has got
  305.   nothing to do with the article itself... It's just one of those titles I
  306.   _HAD_ to put... Don't ask me why... :)
  307.  
  308.     This article is about Pascal Units...
  309.  
  310.     3.1. What the hell is a Unit ?????
  311.  
  312.     To put this simply, a unit is a bunch of routines and other stuff strung
  313.   up together to be used by multiple programms... For example, imagine you
  314.   made a procedure like this:
  315.  
  316.        Procedure StupidThing(A,B:Integer);
  317.        Begin
  318.             Writeln(A*B+B+A-B*B);  { This is just a stupid calculus }
  319.        End;
  320.  
  321.     And you use it in lots of programs you make... Well, so you would have to
  322.   Copy/Paste it a lot, or perhaps re-write it... That would SUCK !!! So, the
  323.   nice guys at Borland joined up, took some elements of another programming
  324.   language (invented by the same guy that invented Pascal, N.Wirth) called
  325.   Modula-2 and created UNITS !
  326.     How do you use a unit ?
  327.     Well, you make one of the first lines of your program like this:
  328.  
  329.           Uses MyStUnit;
  330.  
  331.     And then, when you need procedure StupidThing, you don't have to write
  332.   all the procedure in the procedure declaration area of your program... By
  333.   using units, you make your program more organized, as you save precious time
  334.   and fingertips... By using units, the following program would run:
  335.  
  336.       Program TestUnit;
  337.  
  338.       Uses MyStUnit;
  339.  
  340.       Begin
  341.            StupidThing(1,2);
  342.            StupidThing(3,4);
  343.            StupidThing(5,6);
  344.       End.
  345.  
  346.     Well, if you run out for the keyboard and wrote that program, and then you
  347.   run it, you will get a 'File Not Found' error... :(
  348.     That's because you haven't defined the unit !!!
  349.  
  350.     3.2. Defining a Unit
  351.  
  352.     To define a Unit, you just make this:
  353.  
  354.     - The first line of code in a unit must be
  355.  
  356.                         Unit <name>;
  357.  
  358.     - Then, the unit will be splited in three parts... The interface part,
  359.       the implementation part and the startup-code part
  360.  
  361.       3.2.1. Interface
  362.  
  363.       This is were you define what can be acessed by a program... You will tell
  364.     what procedures, functions, variables and other stuff can be called from
  365.     your program... This section starts with the word 'Interface'. So the next
  366.     piece of code is a valid Interface section:
  367.  
  368.              Interface
  369.  
  370.              Const SpellConst=1000;
  371.  
  372.              Type SpellRec=Record
  373.                                  Alfa:Word;
  374.                                  Beta:Byte;
  375.                            End;
  376.  
  377.              Var SpellVar1:Integer;
  378.                  SpellVar2:SpellRec;
  379.  
  380.              Procedure StupidThing(A,B:Integer);
  381.              Function SpellFunc(A:Integer):Word;
  382.  
  383.       Note that you don't include the code of the procedure MyStupidThing in
  384.     the interface section... That goes in the implementation seccion.
  385.  
  386.       3.2.2. Implementation
  387.  
  388.       This is were the code of the functions and procedures defined in the
  389.     interface section, alongside with other variables, constants and types
  390.     that are to be internally used by the procedures and functions, and that
  391.     are not acessible by the main program. This section starts with the word
  392.     'Implementation'. This is a valid counterpart of the above Interface
  393.     section:
  394.  
  395.              Implementation
  396.  
  397.              Const HiddenConst=255;
  398.  
  399.              Procedure IntProc; { This is an internal procedure }
  400.              Begin
  401.                   Writeln('Hidden Constant=',HiddenConst);
  402.              End;
  403.  
  404.              Procedure StupidThing(A,B:Integer);
  405.              Begin
  406.                   Writeln(A*B+B+A-B*B);
  407.              End;
  408.  
  409.              Function SpellFunc(A:Integer):Word;
  410.              Begin
  411.                   SpellFunc:=Abs(A)*2;
  412.                   IntProc;
  413.              End;
  414.  
  415.       3.2.3. Startup-Code
  416.  
  417.       This is a small part of the unit, that is only usefull sometimes... It
  418.     is a part of a program (like standart Pascal program), but it is only
  419.     executed once, when the unit is linked (see the meaning of this down).
  420.       This is a valid Startup-Code section, for the above examples:
  421.  
  422.              Begin
  423.                   StupidThing(10,20);
  424.              End.
  425.  
  426.       3.2.4. The final Unit
  427.  
  428.       The Unit I built in the example would become something like this:
  429.  
  430.              Unit MyStUnit;
  431.  
  432.              Interface
  433.  
  434.              Const SpellConst=1000;
  435.  
  436.              Type SpellRec=Record
  437.                                  Alpha:Word;
  438.                                  Beta:Byte;
  439.                            End;
  440.  
  441.              Var SpellVar1:Integer;
  442.                  SpellVar2:SpellRec;
  443.  
  444.              Procedure StupidThing(A,B:Integer);
  445.              Function SpellFunc(A:Integer):Word;
  446.  
  447.              Implementation
  448.  
  449.              Const HiddenConst=255;
  450.  
  451.              Procedure IntProc; { This is an internal procedure }
  452.              Begin
  453.                   Writeln('Hidden Constant=',HiddenConst);
  454.              End;
  455.  
  456.              Procedure StupidThing(A,B:Integer);
  457.              Begin
  458.                   Writeln(A*B+B+A-B*B);
  459.              End;
  460.  
  461.              Function SpellFunc(A:Integer):Word;
  462.              Begin
  463.                   SpellFunc:=Abs(A)*2;
  464.                   IntProc;
  465.              End;
  466.  
  467.              Begin
  468.                   StupidThing(10,20);
  469.              End.
  470.  
  471.       When you have the whole unit code, you save it to disk ( NOTE: You must
  472.     use the same name for the Unit and for the file you store the unit).
  473.       Now, you can run the first program I gave you in this article...
  474.  
  475.       3.2.5. Valid and invalid instruction
  476.  
  477.       The folowing instructions are valid, using the above unit:
  478.  
  479.              - WriteLn(SpellConst);
  480.  
  481.              - Var A:SpellRec;
  482.  
  483.              - SpellVar1:=100;
  484.  
  485.              - SpellVar2.Alpha:=4362;
  486.  
  487.              - StupidThing(A,10);
  488.  
  489.              - A:=SpellFunc(-1002);
  490.  
  491.       And the following intructions are _NOT_VALID_ :
  492.  
  493.              - Writeln(HiddenConst);
  494.  
  495.              - IntPro;
  496.  
  497.     3.3. Other Unit-related stuff
  498.  
  499.       Number One: YOU CAN'T RUN A UNIT !!! :) Units are to be integrated in
  500.                   a program (called the main program), and are of no use by
  501.                   themselves...
  502.  
  503.       Number Two: The header of a procedure/function must be the same in the
  504.                   interface and implementation sections.
  505.  
  506.       Number Three: When in the main program you call a Unit, that unit is
  507.                     compiled and integrated in the main program... This is
  508.                     called the linkage stage of compilation... Linking is
  509.                     getting the units and the program together.
  510.  
  511.       Number Four: When you compile a Unit, a file is generated in disk. That
  512.                    file has a TPU extension and the same name as the file of
  513.                    the unit. So, if you compile 'MyStUnit.PAS', you will get
  514.                    the file 'MyStUnit.TPU'. That file is in machine-code, and
  515.                    you shouldn't erase it, because it makes subsequent
  516.                    compilations faster. Don't worry, that Pascal is smart enough
  517.                    to change the TPU file when you alter the PAS file (as long
  518.                    as you compile it).
  519.  
  520.       Number Five: A Unit can call another Unit... Just add the Uses clause and
  521.                    you can use the procedures and other stuff of another unit.
  522.                    I generally place the Uses clause in the interface section,
  523.                    altough you can put it in the implementation section, as long
  524.                    as you don't use (for example) the records defined in the
  525.                    child-unit in the interface section...
  526.  
  527.     3.4. The CRT Unit
  528.  
  529.     Just to end this article, I'll tell you about a GREAT GREAT GREAT Unit
  530.   Pascal haves...  It is called the CRT units... It is in the Unit directory
  531.   of your copy of Turbo Pascal 6, and it has lots of routines to work with
  532.   text mode. I'll just tell you of some, so that you can have some fun with
  533.   them:
  534.  
  535.        - GotoXY(X,Y) -> This procedure get's the cursor at the position (X,Y).
  536.                         So, if you do:
  537.  
  538.                             GotoXY(10,10);
  539.                             Write('ABC');
  540.  
  541.                         it will appear on the screen's position (10,10) the
  542.                         word 'ABC'... The upper left corner of the screen is
  543.                         (1,1).
  544.  
  545.        - TextColor(C) -> This changes the color of the text you write to color
  546.                          C... You can use constants that are defined in unit
  547.                          CRT, so you can write:
  548.  
  549.                             TextColor(Yellow);
  550.  
  551.                          The other colors available are:
  552.  
  553.                              Black, Blue, Green, Cyan, Red, Magenta,
  554.                              Brown, LightGray, DarkGray, LightBlue,
  555.                              LightGreen, LightCyan, LightRed,
  556.                              LightMagenta and White.
  557.  
  558.                          If you want the text to blink, add 128 to the number
  559.                          of the color... So, if you want text blinking in
  560.                          yellow, do:
  561.  
  562.                             TextColor(Yellow+128);
  563.  
  564.        - TextBackground(C) -> This changes the background color of the text.
  565.                               It is similar to TextColor, and you can use the
  566.                               same constants and all, with the exception of
  567.                               the lighter colors, that can't be used for
  568.                               background (don't ask me why !!)...
  569.  
  570.        - Sound(Freq) -> Does a sound with a frequency of Freq.
  571.  
  572.        - NoSound -> Stops the sound played by the Sound Procedure (it is SOOOO
  573.                     valuable for my ears !!)
  574.  
  575.        - ReadKey -> Waits for a key to be pressed and returns the character
  576.                     corresponding to the key... So, if you do:
  577.  
  578.                             C:=ReadKey;
  579.  
  580.                     and you press the key A, variable C would hold the value
  581.                     'A'...
  582.  
  583.        - KeyPressed -> Returns a boolean variable that states if a key as been
  584.                        pressed or not.
  585.  
  586.     These are the more important ones... To wrap this article, I'll just say
  587.   that you should master the basics of Units, because they are one of the
  588.   more important things in Pascal... I use them _ALWAYS_ !!!!
  589.  
  590.  
  591. -x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-
  592.  
  593.  
  594.   4. Boolean Algebra - Another look at conditions
  595.  
  596.     I've talked about conditions in issue two, in a basic manner... In this
  597.   issue we'll expand the knowledge built in that issue.
  598.  
  599.     I've said in that issue that boolean algebra is an algebra that gives
  600.   only TRUE or FALSE as results... But what I didn't said back then is that
  601.   you have lots of operations that give boolean results. I talked about
  602.   operation with two operators (binary operations). They were operations that
  603.   compared two operands of the same type (were they characteres or numbers).
  604.   Now, I will show the use of boolean operations, that is, operation in which
  605.   the operands are of type boolean. There is one unary operation (operation
  606.   that only uses one operand), and several binary operations...
  607.  
  608.     4.1. NOT
  609.  
  610.     The NOT operation is fairly simple... Imagining you have a boolean
  611.   variable or expression, if you NOTed it, it would inverse... Imagine this:
  612.  
  613.                  A:=10;
  614.                  B:=5;
  615.                  C:=A<B;
  616.                  D:=NOT(C);
  617.  
  618.     Varibale C would have the value FALSE, but D would have the value TRUE...
  619.   NOT inverts the operand... The truth table of this operation is the
  620.   following:
  621.                         _________________
  622.                         |   A   | NOT A |
  623.                         |---------------|
  624.                         | TRUE  | FALSE |
  625.                         | FALSE | TRUE  |
  626.                         -----------------
  627.  
  628.     NOTE: The NOT operation is also know as negation, complement or first
  629.   complement.
  630.  
  631.     4.2. AND
  632.  
  633.     The AND operation is a binary operation... It's simple to think of what is
  634.   it's function... It combines two operands, and if the both operands are TRUE,
  635.   it returns the value TRUE, otherwise it returns FALSE. Example:
  636.  
  637.                  A:=10;
  638.                  B:=5;
  639.                  C:=1;
  640.                  D:=A>B;      -> This is TRUE
  641.                  E:=A<B;      -> This is FALSE
  642.                  F:=C<A;      -> This is TRUE
  643.                  G:=D AND E   -> This is FALSE
  644.                  H:=D AND F   -> This is TRUE
  645.  
  646.     Don't forget that:
  647.  
  648.                  D:=A>B;
  649.                  E:=A<B;
  650.                  G:=D AND E;
  651.  
  652.     is equal to:
  653.  
  654.                 G:=(A>B) AND (A<B);
  655.  
  656.     Don't forget the parentesis, or you will get an error message (try to
  657.   figure out why... :) ).
  658.     The truth table is this:
  659.                         ___________________________
  660.                         |   A   |   B   | A AND B |
  661.                         |---------------|---------|
  662.                         | TRUE  | TRUE  |  TRUE   |
  663.                         | TRUE  | FALSE |  FALSE  |
  664.                         | FALSE | TRUE  |  FALSE  |
  665.                         | FALSE | FALSE |  FALSE  |
  666.                         ---------------------------
  667.  
  668.     4.3. OR
  669.  
  670.     The OR operation is a binary operation... Like in AND, it's name is self-
  671.   -expainatory. It's simple to think of what is it's function... It combines
  672.   two operands, and if any one of the operands are TRUE, it returns the value
  673.   TRUE, otherwise it returns FALSE. Example:
  674.  
  675.                  A:=10;
  676.                  B:=5;
  677.                  C:=1;
  678.                  D:=A>B;      -> This is TRUE
  679.                  E:=A<B;      -> This is FALSE
  680.                  F:=C>A;      -> This is FALSE
  681.                  G:=D OR E    -> This is TRUE
  682.                  H:=E OR F    -> This is FALSE
  683.  
  684.     The truth table is like this:
  685.                         ___________________________
  686.                         |   A   |   B   | A OR  B |
  687.                         |---------------|---------|
  688.                         | TRUE  | TRUE  |  TRUE   |
  689.                         | TRUE  | FALSE |  TRUE   |
  690.                         | FALSE | TRUE  |  TRUE   |
  691.                         | FALSE | FALSE |  FALSE  |
  692.                         ---------------------------
  693.  
  694.     4.4. XOR (eXclusive OR)
  695.  
  696.     The XOR operation is almost equal to the OR operation, except in the case
  697.   in which A and B are both TRUE... In that case, A XOR B is equal to FALSE.
  698.  
  699.     The truth table is like this:
  700.                         ___________________________
  701.                         |   A   |   B   | A XOR B |
  702.                         |---------------|---------|
  703.                         | TRUE  | TRUE  |  FALSE  |
  704.                         | TRUE  | FALSE |  TRUE   |
  705.                         | FALSE | TRUE  |  TRUE   |
  706.                         | FALSE | FALSE |  FALSE  |
  707.                         ---------------------------
  708.  
  709.     4.5. Rules of Boolean Algebra
  710.  
  711.     There are some rules that can help simplify some complex boolean
  712.   expressions. They are fairly intuitive and easy to demonstrate...
  713.   They are the following:
  714.  
  715.       - X OR FALSE     = X
  716.       - X OR TRUE      = TRUE
  717.       - X OR X         = X
  718.       - X OR NOT(X)    = TRUE
  719.  
  720.       - X AND TRUE     = X
  721.       - X AND FALSE    = FALSE
  722.       - X AND X        = X
  723.       - X AND NOT(X)   = FALSE
  724.  
  725.       - NOT ( NOT(X))  = X
  726.  
  727.       (Commutative)
  728.       - X OR Y         = Y OR X
  729.       - X AND Y        = Y AND X
  730.  
  731.       (Associative)
  732.       - X OR (Y OR Z)  = (X OR Y) OR Z
  733.       - X AND (Y AND Z)= (X AND Y) AND Z
  734.  
  735.       (Distributive)
  736.       - X AND (Y OR Z) = (X AND Y) OR (X AND Z)
  737.       - X OR (Y AND Z) = (X OR Y) AND (X OR Z)
  738.  
  739.       (De Morgan)
  740.       - NOT (X OR Y)   = NOT(X) AND NOT(Y)
  741.       - NOT (X AND Y)  = NOT(X) OR NOT(Y)
  742.  
  743.     4.6. Using Boolean algebra
  744.  
  745.       You can use boolean algebra in expressions in your If, While and
  746.     Repeat..Until sentences. Just use the rules suplied and it is easy.
  747.     Examples:
  748.  
  749.              If (A>B) AND (B<C) Then ......
  750.  
  751.              If (A=B) OR (A>C) Then .......
  752.  
  753.              If Not(A=B) Then .............
  754.  
  755.              While Not(A<B) Do ............
  756.  
  757.              Repeat
  758.              ..............................
  759.              Until (A=B) AND (D=E);
  760.  
  761.     Hope this article was good and usefull... As always, I recommend you
  762.   to experiment, in order to get higher learning... Remember, only the wise
  763.   and the fools don't experiment, thus, they don't change... :)
  764.  
  765.  
  766. -x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-
  767.  
  768.  
  769.   5. Our friend, the pointer - Part II
  770.  
  771.     This article, as you may already guessed, is the follow-up to an article
  772.   I made on issue one. If you don't recall, or if you didn't read it, get issue
  773.   one and read it...
  774.  
  775.     The problem with the pointer structure of Part I of this article is that
  776.   the size of the structure was rigid... It did had to be already defined.
  777.   This is good for lookup tables, but it is no good for other uses...
  778.   Check out this example:
  779.  
  780.     Lets imagine you wanted to make an image handling library, that could read
  781.   images of various sizes and move them on the screen.
  782.     You know that we should use pointers to store the images (because you can
  783.   have the possibity that the combined sizes of the images is bigger than
  784.   64 Kb). But, using the method taught in Part I, all the images should have
  785.   the same size... But we want to have images of several sizes, so the size
  786.   of a pointer must be determined at run-time, rather than in compile-time.
  787.   If you are adventerous, you already have investigated further the GetMem and
  788.   FreeMem procedures, and you already know how to do this. I will explain for
  789.   the rest of you out there. This is an (incomplete) example:
  790.  
  791.            Type Image=Record
  792.                             Xsize,Ysize:Word;
  793.                             Data:Pointer;
  794.                       End;
  795.                       ..............
  796.                       ..............
  797.                       ..............
  798.            Procedure LoadImage(Filename:String;Var Pic:Image);
  799.            Var F:File;
  800.            Begin
  801.                 Assign(F,Filename);
  802.                 Reset(F,1);
  803.                 BlockRead(F,Pic.Xsize,2); { Read the X size of the image);
  804.                 BlockRead(F,Pic.Ysize,2); { Read the Y size of the image);
  805.                 GetMem(Pic.Data,Xsize*Ysize);
  806.                 BlockRead(F,Pic.Data^,Xsize*Ysize);
  807.                 Close(F);
  808.            End;
  809.                      ...............
  810.                      ...............
  811.            Procedure KillImage(Var Pic:Image);
  812.            Begin
  813.                 Freemem(Pic.Data,Pic.Xsize*Pic.Ysize);
  814.            End;
  815.  
  816.     In the theory side, just think about this. You read first the horizontal
  817.   and vertical sizes and store them in variables. Then, you know you need
  818.   (Xsize*Ysize) bytes to store an image of that size, so you allocate them
  819.   with GetMem. In the end, when the image is no longer needed, you deallocate
  820.   the space of the pointer with Freemem... Did you understand ?
  821.     You can dinamically allocate space, using GetMem and FreeMem...
  822.     I think this is fairly simple to grasp concepts, that with practice become
  823.   part of your nature...
  824.     To end this article, I will leave with this problem... Imagine you needed
  825.   a enlarging procedure, that given an image, it would expand the image to
  826.   double it's size... You can't change the size of a pointer without first
  827.   destroying the contents... There are ways to get around this... One of them
  828.   is not suited for this example, but it will be the one that I will teach in
  829.   the Part III of this series of articles. The other way, that can really be
  830.   used in this example is to use another pointer, that stores the enlarged
  831.   image...
  832.  
  833.  
  834. -x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-
  835.  
  836.  
  837.   6. The Lens Effect
  838.  
  839.     To explain the lens effect, I must first define how to do a
  840.   transformation of any kind... Then, I'll explain how to do the maths for
  841.   a lens... Reading just the first part, you get a nice idea on how to do
  842.   mirroring, and other effects like that...
  843.  
  844.     6.1. Transformations
  845.  
  846.     Lets think of a transformation like this: you have a section of the
  847.   screen on which you want to do a transformation.
  848.     Consider the smallest rectangule that encompasses all the transformation.
  849.     To increase speed, let's assume that the transformation is precalculated
  850.   (this is different of an animation !). As the transformation is
  851.   precalculated, you know the size of the blue rectangle. Let's call that
  852.   size SIP (Size In Pixels).
  853.   So, I need three arrays: ORIGIN[SIP], TRANS[SIP] and DEST[SIP].
  854.  
  855.   Note: I will build up an example of real code in Pascal, during the
  856.         explanation... It will be in between {}.
  857.  
  858.          Assuming the size is 30x30
  859.          const xsize=30;
  860.                ysize=30;
  861.          var ORIGIN, TRANS, DEST:array[1..xsize*ysize] of byte;
  862.  
  863.   Another note: When I talk about image, I'm talking about the part of the
  864.                 screen you want to process.
  865.  
  866.     ORIGIN stores the original image. You must update this array, everytime
  867.   you change the image...
  868.  
  869.          Procedure UpdateOrigin(x,y:word);
  870.          var a,b:integer;
  871.          begin
  872.               for a:=0 to xsize-1 do for b:=0 to ysize-1 do
  873.                   ORIGIN[b*xsize+1]:=getpixel(a+x,b+y);
  874.          end;
  875.  
  876.     The parameters on this procedure are the x and y coordinates of the
  877.   upper left corner of the image.
  878.     Getpixel is a routine that returns the color of the point at the given
  879.   coordinates. This obviously depends on the resolution.
  880.  
  881.     Now, we must operate the transformation... We want to convert the array
  882.   ORIGIN in the array DEST, with the effect... So, DEST is ORIGIN transformed...
  883.     So, you must calculate each of the pixels of DEST with base on ORIGIN.
  884.     You must determine the new value for each pixel of ORIGIN and store it in
  885.   DEST... To know what is the new value, we use the array TRANS, that is a
  886.   constant, and therefore can be calculated in advance. For each effect,
  887.   this array is different, so you can use the same basic routines for lots
  888.   of effects, just changing the calculation of TRANS.
  889.  
  890.     This array says for each pixel: the pixel at position A in DEST, should
  891.   be the same as the pixel at position TRANS[A] in ORIGIN.
  892.   So the formula is DEST[A] = ORIGIN[TRANS[A]] for all elements.
  893.   The transformation is fast, and does not depend on the resolution/video-mode.
  894.  
  895.     We now copy the array DEST to the screen, and the transformation is
  896.   complete.
  897.  
  898.     If you want the transformation to move (i.e. the lens move), you must
  899.   update ORIGIN for every change in position. Note: Don't forget to replace
  900.   the transformed image with the original image before you move...
  901.  
  902.     Just as an example of transfomation, here it is the calculation of a
  903.   transformation array that magnifies the upper left corner by a factor
  904.   of MAG (MAG is a variable of type byte).
  905.  
  906.               Procedure CalcMatrix;
  907.               Begin
  908.               For A:=0 To ysize-1 do
  909.                   For B:=0 To dX-1 do
  910.                   TRANS[A*xsize+B]:=(A div MAG)*Xsize+(B div MAG);
  911.               End;
  912.  
  913.     Note: You should use a virtual screen if you don't want your screeen to
  914.           flicker like mad !
  915.  
  916.     6.2. How to make the lens transformation
  917.  
  918.     Calculating the transformation matrix for the lens, here is were the
  919.   trouble begins... This envolves lots of maths and a bit of thinking...
  920.  
  921.     Consider a sphere S, intersecting with a plane A. This defines a circle C in
  922.   the plane. Define Rc as the ray of the circle C, Rs as the ray of the
  923.   sphere S, and d as the distance from the centre of the sphere to the plane A.
  924.     We know then that:
  925.                              Rc^2 + d^2 = Rs^2           (1)
  926.  
  927.     If you want several lenses with the same radius, but different
  928.   lens-strength, then you must preserve the same value for Rc. If the size
  929.   of the transformed area is L by L pixels (the lens is circular, so the
  930.   involved area is a square) then Rc should be L/2. The distance d determines
  931.   the strength of the lens. So, knowing Rc and d, we can determine Rs.
  932.  
  933.     Suppose we're given L (so Rc = L/2), we made a choice for d, and we
  934.   calculated the value of Rs. We now want to transform each pixel in the
  935.   square (LxL).
  936.     We simply check all pixels (2 loops: one for the X-axis and one for the
  937.   Y-axis).
  938.     We call the point we're transforming P. If P lies outside or on C, then the
  939.   point isn't transformed. That is: TRANS(P)=P; if (x,y) are the coordinates of
  940.   P than TRANS[x+y*L] := x+y*L.
  941.  
  942.     If P lies within the C, then the point will be transformed:
  943.   the idea behind the effect is to project the points as if they are
  944.   magnified, that is, the points within the circle must be projected from
  945.   the center of the sphere to the sphere...
  946.  
  947.                                 EYE
  948.                                  |
  949.                                 \|/
  950.  
  951.  
  952.  
  953.  
  954.  
  955.  
  956.                               _______
  957.                             _-       -q      
  958.                            /         /|\
  959.                           /         / | \                 A
  960.             -------------|---------i--p--|-----------------
  961.                          | d      /      |
  962.                          | ------O       |       <-- This is supposed to 
  963.                                                      be circle... Don't 
  964.                                                      blame me if my 
  965.                                                      ASCII art sucks !! 
  966.                                                      Ask me for a GIF if you 
  967.                                                      want a clear picture..
  968.  
  969.     Hence, for a given point p, we determine the point q (see picture). That
  970.   point q is the projection of some point i within the circle C, so from
  971.   the point q, we draw a line to the centre of the sphere, thus defining
  972.   the point i, which is the intersection of that line whith the plane. That
  973.   is the transformation of the point p: TRANS(p)=i, because: if the point i
  974.   was to be projected on the sphere, it would end up at the point q. Since
  975.   we're looking straight onto the plane, the points q and p are the same
  976.   (that is: they end up at the same point on your screen).
  977.  
  978.     When implementing, you can use some shortcuts:
  979.   Lets say L and d are given. Then Rc=L/2;
  980.   Consider the origin of a rectangular system in the centre of the circle C.
  981.   The X-axis and the Y-axis are parallel to the plane A, in such a way that
  982.   the square that is to be transformed, is defined as:
  983.  
  984.                    [-Rc,Rc] x [-Rc,Rc]
  985.  
  986.     The orientation of the Z-axis is such that the coordinates of the centre of the
  987.   sphere are (0,0,-d). The sphere is given by:
  988.  
  989.                  x^2 + y^2 + (z+d)^2 = Rs^2                   (2)
  990.  
  991.     hence:  [ (1) ]
  992.  
  993.                  x^2 + y^2 + (z+d)^2 = Rc^2 + d^2              (3)
  994.  
  995.     Consider the point P within the circle C. Thus, its coordinates are:
  996.  
  997.            (Px,Py,0)     and       Px^2 + Py^2 < Rc^2        (4)
  998.  
  999.  
  1000.     The coordinates of the point Q can be found through this system:
  1001.  
  1002.         |   x = Px            A - defines the line, parrallel to the Z-axis
  1003.         |   y = Py                through the point P.
  1004.         |   x^2 + y^2 + (z+d)^2 = Rc^2 + d^2
  1005.  
  1006.     We immediatly find Qx and Qy (Qx=Px; Qy=Py), and for Qz we find:
  1007.  
  1008.         Px^2 + Py^2 + Qz^2 + 2*d*Qz + d^2 = Rc^2 + d^2
  1009.  
  1010.         Qz^2 + 2*d*Qz - Rc^2 + Px^2 + Py^2 = 0
  1011.  
  1012.         D = d^2 -  (Px^2 + Py^2 - Rc^2)                       (5)
  1013.  
  1014.         since  Rc^2 > Px^2 + Py^2    [ (4) ],  we find D>0, and
  1015.  
  1016.         Qz = 1+-sqrt(D).
  1017.  
  1018.     We find 2 solutions (the line intersects the sphere twice !), but consider
  1019.   only the one with Qz>0. We find coordinates for Q:
  1020.  
  1021.         (Qx,Qy,Qz) == (Px,Py,1+sqrt(D))    <see (5) for D>      (6)
  1022.  
  1023.     Finally, we find the coordinates of the point I through :
  1024.  
  1025.       (Sx,Sy,Sz) are the coordinates of the centre of the sphere
  1026.       (Sx,Sy,Sz) == (0,0,-d)
  1027.  
  1028.          |      ( z - Sz)  
  1029.          |  x = --------- * (Qx-Sx) + Sx        
  1030.          |      (Qz - Sz)                       < defines the line through
  1031.          |                                      < the centre of the sphere
  1032.          |      ( z - Sz)                       < and the point Q
  1033.          |  y = --------- * (Qy-Sy) + Sy        
  1034.          |      (Qz - Sz)
  1035.          |
  1036.          |  z = 0                               <- defines the plane A
  1037.  
  1038.          We find:
  1039.  
  1040.                   ( 0 - (-d) )
  1041.            Ix  =  ------------ * (Qx-0) + 0
  1042.                   ( Qz - (-d))
  1043.  
  1044.                   ( 0 - (-d) )
  1045.            Iy  =  ------------ * (Qy-0) + 0
  1046.                   ( Qz - (-d))
  1047.  
  1048.            Iz  =  0
  1049.  
  1050.  
  1051.          hence:
  1052.                       d
  1053.            Ix  =  --------- Qx
  1054.                    Qz + d
  1055.  
  1056.                       d
  1057.            Iy  =  --------- Qy
  1058.                    Qz + d
  1059.  
  1060.            Iz  =  0
  1061.  
  1062.  
  1063.     We know the coordinates of Q (they can be fully determined if the
  1064.   coordinates of P are known), and we know d, so I can be calculated.
  1065.     We could than say:
  1066.  
  1067.     TRANS[ (L/2+Px) + (L/2+Py) * L ] := (L/2+Ix) + (L/2+Iy) * L;
  1068.  
  1069.     Now, you can see (by just observing the drawing, or by checking the
  1070.   formulas) that if we find
  1071.  
  1072.      TRANS[p(Px,Py)]=i(Ix,Iy)
  1073.  
  1074.     then also
  1075.  
  1076.      TRANS[p( Px,-Py)]=i( Ix,-Iy)
  1077.      TRANS[p(-Px, Py)]=i(-Ix, Iy)
  1078.      TRANS[p(-Px,-Py)]=i(-Ix,-Iy)
  1079.  
  1080.     so that the entire transformation can be defined be calculating a
  1081.   quarter of the transformed area.
  1082.  
  1083.     So, get yourself coding... I don't have any working examples, and I
  1084.   didn't had time/pacience to code one, so try yourself... After the
  1085.   formulas, it should be fairly easy...
  1086.  
  1087.     This article is slightly different because I did it for a newsgroup, not
  1088.   for 'The Mag'... I apologize if you don't like it very much...
  1089.  
  1090.  
  1091. -x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-
  1092.  
  1093.  
  1094.   7. Graphics Part VI - Scrolling Part I
  1095.  
  1096.     This is the first of a two part article, dedicated to scrolling.
  1097.  
  1098.     There are so many ways to scroll, and so different concepts of scrolling
  1099.   that it is _VERY_ hard to write an article about it. But I'll do my best...
  1100.  
  1101.     NOTE: I have put _ALL_ the procedures given in previous numbers of 'The Mag'
  1102.           in a unit called MODE13h... This unit can be found with this issue of
  1103.           'The Mag'. This units is supposed to grow from issue to issue, so
  1104.           make sure you have it up to date...
  1105.           If you don't know what a unit is, refer to the first article of this
  1106.           issue...
  1107.           Also, with this issue, you'll get two PCX files, for the example
  1108.           programms. One of them ('SPELL.PCX') was drawn by me (I know, crappy
  1109.           egocentric picture), and the other ('LANDSCAP.PCX') was also 'drawn'
  1110.           by me in Vista Pro (I know it's hard to do a bad Vista picture).
  1111.  
  1112.     7.1. What is scrolling ?
  1113.  
  1114.     Scrolling is when you move the screen (or part of it) from one place to
  1115.   another... In other words, it is a translatation of the screen.
  1116.     Now, in computer terms, what's scrolling ?
  1117.     Scrolling is based on memory moves... You move the memory around in a way
  1118.   that it seems that the screen itself is moving... Confused already ? :)
  1119.     Tough this seams complicated, it is fairly easy... In the first part of
  1120.   this articles, I will explain you Wipe Scrolls, and other kinds of scrolls
  1121.   that I can't really define... I can't explain all about of scrolling, but
  1122.   I'll explain the concepts behind it, so if you think a little you can
  1123.   determine how to make the effect you require. Also, in this first part, I
  1124.   will only talk about full-screen scrolls... Partial scrolls will be discussed
  1125.   in part II of the Scrolling Saga !! :)
  1126.  
  1127.     7.2. Wipe Scrolls
  1128.  
  1129.     A wipe scroll is a type of scrolling that is used for cleaning the screen.
  1130.   For example, let's imagine you have a very nice PCX image displayed on your
  1131.   screen, and you want it to scroll up, until it disappears. This is fairly
  1132.   easy to do... You simply copy all lines on the screen to the line above that
  1133.   one. You do it like this:
  1134.  
  1135.        Program Scroll_Up;
  1136.  
  1137.        Uses Mode13h;            { This uses the Mode13h unit }
  1138.  
  1139.        Var A:Integer;
  1140.  
  1141.        Procedure ScrollUp;
  1142.        Begin
  1143.             WaitVbl;
  1144.             Move(Mem[VGA:320],Mem[VGA:0],63680);
  1145.        End;
  1146.  
  1147.        Begin
  1148.             Initgraph;
  1149.             LoadPCX('Spell.Pcx',VGA);
  1150.             For A:=0 To 200 Do ScrollUp;
  1151.             Readln;
  1152.             Closegraph;
  1153.        End.
  1154.  
  1155.     See the image going up until it disappears ?
  1156.     The Move instruction moves the second line to the first line, the third
  1157.   line to the second, and so forth, until the 200th line goes to the 199th
  1158.   line. The first line is discarted... If you still can't understand think
  1159.   about this: The address of the second line in mode 13h is A000:0320, and the
  1160.   address of the first line is A000:0000... So, to scroll up, you move the
  1161.   memory from A000:0320 to A000:0000... And, because you want scroll all lines
  1162.   from the second to the last, you move 64000-320 bytes, that is 63680 bytes.
  1163.     If you want to scroll down, you just move the memory from A000:0000 to
  1164.   A000:0320... Simple like this:
  1165.  
  1166.        Procedure ScrollDown;
  1167.        Begin
  1168.             WaitVbl;
  1169.             Move(Mem[VGA:0],Mem[VGA:320],63680);
  1170.        End;
  1171.  
  1172.     To scroll right or left isn't that easy. To scroll left, for example:
  1173.  
  1174.               A000:0001 moves to A000:0000
  1175.               A000:0321 moves to A000:0320
  1176.               And so forth...
  1177.  
  1178.     So, you can't move all the memory with just one command... To scroll
  1179.   left, you'll have to scroll each line individually... Like this:
  1180.  
  1181.        Procedure ScrollLeft;
  1182.        Var A:Byte;
  1183.        Begin
  1184.             WaitVbl;
  1185.             For A:=0 To 199 Do
  1186.             Move(Mem[VGA:(320*A+1)],Mem[VGA:(320*A)],319);
  1187.        End;
  1188.  
  1189.     And to scroll right:
  1190.  
  1191.        Procedure ScrollRight;
  1192.        Var A:Byte;
  1193.        Begin
  1194.             WaitVbl;
  1195.             For A:=0 To 199 Do
  1196.             Move(Mem[VGA:(320*A)],Mem[VGA:(320*A+1)],319);
  1197.        End;
  1198.  
  1199.     So far, so good, right ? WRONG !!! Try to scroll the other picture,
  1200.   LANDSCAP.PCX... Look at the trail it leaves behind. That's ugly, isn't it ?
  1201.     Well, why does it happen ?
  1202.     It happens because you don't change the first line (in the case of the
  1203.   ScrollDown), the last line (in the case of the ScrollUp), the first pixel
  1204.   of every line (in case of the ScrollRight) or the last pixel of every line
  1205.   (in case of the ScrollLeft). So, let's clear it to black... The new scroll
  1206.   procedures are like this:
  1207.  
  1208.        Procedure ScrollUp;
  1209.        Begin
  1210.             WaitVbl;
  1211.             Move(Mem[VGA:320],Mem[VGA:0],63680);
  1212.             Line(0,199,319,199,0,VGA);
  1213.        End;
  1214.  
  1215.        Procedure ScrollDown;
  1216.        Begin
  1217.             WaitVbl;
  1218.             Move(Mem[VGA:0],Mem[VGA:320],63680);
  1219.             Line(0,0,319,0,0,VGA);
  1220.        End;
  1221.  
  1222.        Procedure ScrollLeft;
  1223.        Var A:Byte;
  1224.        Begin
  1225.             WaitVbl;
  1226.             For A:=0 To 199 Do
  1227.                Move(Mem[VGA:(320*A+1)],Mem[VGA:(320*A)],319);
  1228.             Line(319,0,319,199,0,VGA);
  1229.        End;
  1230.  
  1231.        Procedure ScrollRight;
  1232.        Var A:Byte;
  1233.        Begin
  1234.             WaitVbl;
  1235.             For A:=0 To 199 Do
  1236.                Move(Mem[VGA:(320*A)],Mem[VGA:(320*A+1)],319);
  1237.             Line(0,0,0,199,0,VGA);
  1238.        End;
  1239.  
  1240.     The ideia is to put a black line in the certain place, so that it clears
  1241.   that part of the screen, so that the scroll won't leave a trail...
  1242.  
  1243.     7.3. Other Scrolls
  1244.  
  1245.     If you re-think the last concept, the one about clearing a part of the
  1246.   screen, you will be able to do a lot more effects... For instance, type
  1247.   the following code:
  1248.  
  1249.        Program Landscape;
  1250.  
  1251.        Uses Mode13h,Crt;
  1252.  
  1253.        Var Height:Integer;
  1254.  
  1255.        Procedure ScrollLeft;
  1256.        Var A:Byte;
  1257.        Begin
  1258.             WaitVbl;
  1259.             For A:=0 To 199 Do
  1260.                Move(Mem[VGA:(320*A+1)],Mem[VGA:(320*A)],319);
  1261.             Line(319,0,319,199,0,VGA);
  1262.  
  1263.             Height:=Height+Random(5)-2;
  1264.             If Height<2 Then Height:=2;
  1265.             Line(319,199-Height,319,199,1,VGA);
  1266.  
  1267.        End;
  1268.  
  1269.        Begin
  1270.             Randomize;
  1271.             Initgraph;
  1272.             SetColor(0,0,0,0);
  1273.             SetColor(1,0,63,0);
  1274.             Height:=50;
  1275.             Repeat
  1276.                   ScrollLeft;
  1277.             Until Keypressed;
  1278.             Closegraph;
  1279.        End.
  1280.  
  1281.     See the landscape (YECH!) scrolling right in the screen ? Ok, it isn't
  1282.   very nice, but it's just to show you something...
  1283.     Notice that in the ScrollLeft procedure we've added the following lines:
  1284.  
  1285.             Height:=Height+Random(5)-2;
  1286.             If Height<2 Then Height:=2;
  1287.             Line(319,199-Height,319,199,1,VGA);
  1288.  
  1289.     These are the lines that really draw the landscape... They insert a new
  1290.   column in the screen... Then, that column is scrolled with the rest of the
  1291.   picture. That gives the illusion of a landscape comming to sight. You can do
  1292.   this with all directions... Check out the Starfield program. The program
  1293.   will scroll a starfield 200 pixels in every direction, including diagonals...
  1294.  
  1295.        Program Starfield;
  1296.  
  1297.        Uses Mode13h,Crt;
  1298.  
  1299.        Var A:Byte;
  1300.  
  1301.        Procedure SetUpStarfield;
  1302.        Var A:Word;
  1303.        Begin
  1304.             { Set up colors... Grey scales }
  1305.             For A:=0 To 15 Do SetColor(A,A*4,A*4,A*4);
  1306.             { Put random starfield in screen }
  1307.             For A:=0 To 500 Do PutPixel(Random(320),Random(200),Random(16),VGA);
  1308.        End;
  1309.  
  1310.        Procedure ScrollUp;
  1311.        Begin
  1312.             WaitVbl;
  1313.             Move(Mem[VGA:320],Mem[VGA:0],63680);
  1314.             Line(0,199,319,199,0,VGA);
  1315.             PutPixel(Random(320),199,Random(16),VGA);
  1316.        End;
  1317.  
  1318.        Procedure ScrollDown;
  1319.        Begin
  1320.             WaitVbl;
  1321.             Move(Mem[VGA:0],Mem[VGA:320],63680);
  1322.             Line(0,0,319,0,0,VGA);
  1323.             PutPixel(Random(320),0,Random(16),VGA);
  1324.        End;
  1325.  
  1326.        Procedure ScrollLeft;
  1327.        Var A:Byte;
  1328.        Begin
  1329.             WaitVbl;
  1330.             For A:=0 To 199 Do
  1331.                Move(Mem[VGA:(320*A+1)],Mem[VGA:(320*A)],319);
  1332.             Line(319,0,319,199,0,VGA);
  1333.             PutPixel(319,Random(200),Random(16),VGA);
  1334.        End;
  1335.  
  1336.        Procedure ScrollRight;
  1337.        Var A:Byte;
  1338.        Begin
  1339.             WaitVbl;
  1340.             For A:=0 To 199 Do
  1341.                Move(Mem[VGA:(320*A)],Mem[VGA:(320*A+1)],319);
  1342.             Line(0,0,0,199,0,VGA);
  1343.             PutPixel(0,Random(200),Random(16),VGA);
  1344.        End;
  1345.  
  1346.        Begin
  1347.             Randomize;
  1348.             Initgraph;
  1349.             SetUpStarfield;
  1350.             For A:=0 To 199 Do ScrollUp;
  1351.             For A:=0 To 199 Do ScrollLeft;
  1352.             For A:=0 To 199 Do ScrollRight;
  1353.             For A:=0 To 199 Do ScrollDown;
  1354.             For A:=0 To 199 Do
  1355.             Begin
  1356.                  ScrollUp;
  1357.                  ScrollLeft;
  1358.             End;
  1359.             For A:=0 To 199 Do
  1360.             Begin
  1361.                  ScrollUp;
  1362.                  ScrollRight;
  1363.             End;
  1364.             For A:=0 To 199 Do
  1365.             Begin
  1366.                  ScrollDown;
  1367.                  ScrollRight;
  1368.             End;
  1369.             For A:=0 To 199 Do
  1370.             Begin
  1371.                  ScrollDown;
  1372.                  ScrollLeft;
  1373.             End;
  1374.             Readln;
  1375.             Closegraph;
  1376.        End.
  1377.  
  1378.     This article is far for completion, because there is so many thing to be
  1379.   said about scrolling, but I will leave that for part II... In that article,
  1380.   I'll discuss partial scrolls and tile scrolling, so look out for it !! :)
  1381.   I will also talk of paralax scrolling, tough that is just a matter of various
  1382.   scrolls moving at different speeds... That involves virtual screens, so it's
  1383.   quite complicated to talk, tough it's easy to implement...
  1384.  
  1385.  
  1386. -x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-
  1387.  
  1388.  
  1389.   8. Hints and Tips
  1390.  
  1391.                 *   - Begginners tip
  1392.                 **  - Medium tip
  1393.                 *** - Advanced tip
  1394.  
  1395.  
  1396.     - Var keyword in procedures (*)
  1397.  
  1398.       Sometimes, you want to change the content of a variable that is passed
  1399.       to a procedure. There are two reasons to do this, but I will explain it
  1400.       later. This is not so easy as you may expect... For example:
  1401.  
  1402.              Program Test_Twenty_Something;   { I lost count !! :))) }
  1403.  
  1404.              Var B:Integer;
  1405.  
  1406.              Procedure Test(C:Integer);
  1407.              Begin
  1408.                   Writeln('Before in the procedure B=',C);
  1409.                   C:=10;
  1410.                   Writeln('After in the procedure B=',C);
  1411.              End;
  1412.  
  1413.              Begin
  1414.                   B:=5;
  1415.                   Writeln('Before in the main program B=',B);
  1416.                   Test(B);
  1417.                   Writeln('After in the main program B=',B);
  1418.                   Readln;
  1419.              End.
  1420.  
  1421.       If you run this, you will see that C:=10; in the procedure doesn't affect
  1422.       variable B in the main program, but only value C in the procedure. If you
  1423.       really want to change variable B, you must use the VAR keyword in the
  1424.       procedure declaration, like this: Procedure Test(Var C:Integer);
  1425.       If you test the above program with that alteration, you will get the
  1426.       desired effect.
  1427.       Why do you want to change a variable within a procedure ? Simple, because
  1428.       you need to in your program... Or that, or you want to make a procedure
  1429.       that returns an array. You can't return a whole array in a function, so
  1430.       you must use a procedure instead, passing the destination array as a
  1431.       parameter.
  1432.  
  1433.  
  1434. -x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-
  1435.  
  1436.  
  1437.   9. Points of View
  1438.  
  1439.     The other day, I was talking to a friend of mine, and he said: 'Spell, why
  1440.   don't you make you mag in C ?'. I turned to him and I said: 'Because I hate
  1441.   C !!!'... I found out that I'm equal to lots of people in the computerscene
  1442.   who hate something that don't use... This is very frequent:
  1443.   Subject A - So, what language/tracker/paint program do you use ?
  1444.   Subject B - Well, I use Pascal/OctaMed/Deluxe Paint IV...
  1445.   Subject A - Yech !! That's so lame !!! I use C/Scream Tracker/Animator, and
  1446.               they rule ! Your programs are so lame... I don't want people
  1447.               to see me talking with a lame person like you... Bye...
  1448.   I know this sounds stupid, but it happens... So, after I said that to my
  1449.   friend, I ammended saying: 'Really, I don't use C, because Pascal is easier
  1450.   and if I want speed or versatility I use 100% assembler...'.
  1451.     So, you should follow this simple rule: Just because someone dislikes a
  1452.   particular program/language/whatever, it doesn't mean that a person should
  1453.   be excluded because of that.
  1454.     Speaking only of languages... Lots of people don't regard me as a great
  1455.   programmer... They think I just plain SUCK because I use Pascal to code my
  1456.   utilities and to join things together... To that people, I just have one
  1457.   thing to say: Lucky you, because you don't have to enter a competition with
  1458.   me... Not because I would win, not at all, but because I would put a very
  1459.   big fight, using only my 'inferior' Pascal, with my 'useless' assembler code.
  1460.     And to those that think that assembler is stupid because it isn't portable,
  1461.   just think about this: Your dear little C and other languages alike were
  1462.   programmed in ASSEMBLER !!!! They must be... And you can't code a GOOD game
  1463.   or demo using only C++ or Visual Basic ! They aren't fast enough and they
  1464.   don't let you use the inner resources of the machine without needing a bit
  1465.   of assembly code... Just using the interrupt 10h you are using assembler !
  1466.   So grow up and learn how to code !! You don't work with a machine, you make
  1467.   the machine work for you... Maybe one day, with the P7 or the likes you will
  1468.   have so much speed that you can code in Basic and still knock out Second
  1469.   Reality out of the Best_Demo_Of_The_World spot, but still that doesn't make
  1470.   you as good a programmer as Psi of Future Crew, or other of my heroes in
  1471.   coding...
  1472.     So, I'll never pay any attencion to those who think I'm a fool/stupid
  1473.   because I use Pascal or Assembler... In the bottom-line, anyone that can use
  1474.   assembler can use C or any other language, and not everyone that can use C
  1475.   can use assembler... Never forget this... Your precious C compiler was writen
  1476.   in assembler... And all good things in life are writen in assembler (or they
  1477.   just stink) !
  1478.     I'm sorry this is agressive, but this is true... I'm not saying that C is
  1479.   crap, but I prefer Pascal... That is my choice, but I don't mind you using
  1480.   C... It's your choice... All I'm saying is that ASM rules !
  1481.  
  1482.     Ok, for my next issue, I'll probably finish the series of articles
  1483.   dedicated to pointers, and I'll make part II of the Scrolling Tutorial. Also,
  1484.   I'm going to begin a begginer's tutorial on how to make a simple text
  1485.   adventure... it will explain everything, from the basics (creating a storyline
  1486.   and making maps and stuff) to the implementation of the ideias...
  1487.     I'm also thinking of including an article on 'How to make a cool starfield',
  1488.   and more hints and tips and the adventures of Spellcaster... :) I'm going
  1489.   to try this issue faster, but I don't garanty anything, because I must first
  1490.   create the text adventure, so that I can teach how it was done... ;)
  1491.  
  1492.  
  1493. -x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x
  1494.  
  1495.  
  1496.  10. The adventures of Spellcaster, the rebel programmer of year 2018.
  1497.  
  1498.   Episode 7 - Love in a Time of War
  1499.  
  1500.     We arrived at the Brotherhood's headquarters little after 8. There we could
  1501.   breath again... The escape has been a success.
  1502.   - Well, after this rather shacky start, I think you two need to be formally
  1503.     introduced... - said Gundsen, with a strange tone on his voice.
  1504.   For the first time since I opened the cells at the Sega Prison, I looked at
  1505.   Gundsen's sister eyes. I felt immediatly lost... My heart began to pound
  1506.   faster and faster. I thought I felt my legs trembling and drips of sweat
  1507.   beggining to flow in my whole body. I couldn't say or think anything... All
  1508.   I could see were those dark brown eyes, and the apparently soft and beutifull
  1509.   skin that was around them... Gundsen cough, as to call me to reality. It took
  1510.   me a couple more seconds to regain my self control, and to be able to look
  1511.   at rest of Gundsen's sister. She had straigh hair, with a very dark tone of
  1512.   brown, that runned down her head until it stopped near the neck. I tried to
  1513.   be discrete when I looked at her body. Her body was perfect in every aspect,
  1514.   with round curves and not a single piece of celulite, unusual for this time.
  1515.   I looked back at her face... Her eyes were glittering, and she had a faint
  1516.   smile on her beutifull lips. Something told me that I didn't was so discrete
  1517.   as I wanted... I smiled back.
  1518.   - Yuhhh !!! Spell !!! Diogo !!!! - shouted Karl, trying to get me back to
  1519.     reality. I didn't responded, and Karl kicked me in the ass, to wake me up.
  1520.   I lost my balance for a couple of seconds, for I wasn't expecting it, and I
  1521.   swinged my body, raising my leg, and halting it just before reaching Gundsen's
  1522.   face.
  1523.   - Lighten up, Spell !!! - he said. - I just wanted to wake you up...
  1524.   - Sorry, Karl... - I smiled. - I was a little distracted... - I continued,
  1525.   looking at the girl.
  1526.   - As I was saying, before you went to cybergroove, this is my sister,
  1527.     Kristie Gundsen, alias known as Excalibur... - Karl said to me. Then he
  1528.     looked at Kristie. - Kristie, this is Diogo 'Spellcaster' Andrade... He's
  1529.     helping me getting into Comptel system...
  1530.   - Pleased to meet you... - she said quickly to me, before looking again at
  1531.     Karl. - Are you still trying that stupid trick ?!!! I can't believe it !
  1532.     You tried for almost five years, without success, and you nearly got
  1533.     yourself killed because of that! It almost got you and it got Rick dead !
  1534.     And you are trying to do it again, this time with a guy that doesn't look
  1535.     like it can code jack-shit !!!! - she looked at me. - No offense
  1536.     intended...
  1537.   - None taken. - I said quitelly, leaving the room... I tought that I shouldn't
  1538.   get in the middle of a family's stuff... I went up to the top floor of the
  1539.   building were we had our HQ, and I looked at the sun, that was orange because
  1540.   of the pollution, and I said to myself:
  1541.   - Can it be ?... Could it happen to me ?... Is it possible... Love in a time
  1542.     of war ?!
  1543.  
  1544.                                              See you in the next issue
  1545.                                             Diogo "SpellCaster" Andrade